package com.mdd.admin.service.order.impl;

import cn.hutool.core.util.ArrayUtil;
import com.alipay.api.AlipayApiException;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.binarywang.wxpay.bean.result.WxPayOrderQueryV3Result;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.google.common.collect.Lists;
import com.mdd.admin.service.goods.IGoodsService;
import com.mdd.admin.service.goods.IOrderGoodsService;
import com.mdd.admin.service.log.IOrderLogService;
import com.mdd.admin.service.order.IOrderService;
import com.mdd.admin.service.refund.IOrderRefundService;
import com.mdd.admin.service.region.IDevRegionService;
import com.mdd.admin.service.service.IAnnualServiceService;
import com.mdd.admin.service.staff.IStaffService;
import com.mdd.admin.service.user.IUserService;
import com.mdd.admin.validate.order.OrderPageParam;
import com.mdd.admin.validate.order.OrderParam;
import com.mdd.admin.vo.finance.FinanceVo;
import com.mdd.admin.vo.log.OrderLogDetailVo;
import com.mdd.admin.vo.order.OrderDetailVo;
import com.mdd.admin.vo.order.OrderListVo;
import com.mdd.admin.vo.order.StatisticsOrderVo;
import com.mdd.admin.vo.staff.StaffDetailVo;
import com.mdd.admin.vo.user.UserVo;
import com.mdd.common.constant.GlobalConstant;
import com.mdd.common.core.PageResult;
import com.mdd.common.dto.OrderDto;
import com.mdd.common.dto.result.OrderPageResultDto;
import com.mdd.common.dto.result.OrderRefundPageResultDto;
import com.mdd.common.entity.address.UserAddress;
import com.mdd.common.entity.goods.Goods;
import com.mdd.common.entity.goods.OrderGoods;
import com.mdd.common.entity.log.OrderLog;
import com.mdd.common.entity.order.Order;
import com.mdd.common.entity.salesman.Salesman;
import com.mdd.common.entity.service.AnnualService;
import com.mdd.common.entity.staff.Staff;
import com.mdd.common.enums.*;
import com.mdd.common.exception.OperateException;
import com.mdd.common.mapper.address.UserAddressMapper;
import com.mdd.common.mapper.order.OrderMapper;
import com.mdd.common.mapper.refund.OrderRefundMapper;
import com.mdd.common.mapper.salesman.SalesmanMapper;
import com.mdd.common.plugin.notice.NoticeDriver;
import com.mdd.common.utils.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 订单实现类
 */
@Service
@Slf4j
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements IOrderService {

    @Resource
    private OrderMapper orderMapper;

    @Resource
    private IDevRegionService regionService;

    @Resource
    private IOrderGoodsService orderGoodsService;

    @Resource
    private IGoodsService goodsService;

    @Resource
    private IOrderLogService orderLogService;

    @Resource
    private IStaffService staffService;

    @Resource
    private IOrderRefundService refundService;

    @Resource
    private IUserService userService;

    @Resource
    private RedisTemplate<String, String> redisTemplate;

    @Resource
    private UserAddressMapper userAddressMapper;

    @Resource
    private SalesmanMapper salesmanMapper;

    @Resource
    private IAnnualServiceService iAnnualServiceService;
	@Resource
	private OrderRefundMapper orderRefundMapper;

    /**
     * 订单列表
     *
     * @param params 搜索参数
     * @return PageResult<OrderListVo>
     */
    @Override
    public PageResult<OrderListVo> list(OrderPageParam params, Boolean isSalesman) {
        Page<OrderPageResultDto> page = new Page<>(params.getPageNo(), params.getPageSize());
        OrderDto pageDto = new OrderDto();
        BeanUtils.copyProperties(params, pageDto);
        Long startTime = StringUtils.isNotEmpty(params.getOrderTimeStart()) ? TimeUtil.dateToTimestamp(params.getOrderTimeStart()) : null;
        Long endTime = StringUtils.isNotEmpty(params.getOrderTimeEnd()) ? TimeUtil.dateToTimestamp(params.getOrderTimeEnd()) : null;
        pageDto.setOrderTimeStart(startTime);
        pageDto.setOrderTimeEnd(endTime);
        pageDto.setOrderType(params.getOrderType());
        Page<OrderPageResultDto> resultDtoPage = orderMapper.page(page, pageDto);
        if (resultDtoPage == null || CollectionUtils.isEmpty(resultDtoPage.getRecords())) {
            return PageResult.iPageHandle(page.getTotal(), page.getCurrent(), page.getSize(), Lists.newArrayList());
        }
        List<OrderListVo> list = new LinkedList<>();
        Map<Integer, String> orderStatusMap = OrderStatusEnum.getMap();
        Map<Integer, String> dispatchMap = OrderDispatchEnum.getMap();
        for (OrderPageResultDto item : resultDtoPage.getRecords()) {
            if(isSalesman && item.getOrderStatus().equals(OrderStatusEnum.WAIT_PAY.getStatus())) {
                continue;
            }
            OrderListVo vo = new OrderListVo();
            BeanUtils.copyProperties(item, vo);
            if (OrderStatusEnum.CLOSE.getStatus() == item.getOrderStatus()) {
                vo.setDeleteBtn(1);
            } else if (OrderStatusEnum.SERVICING.getStatus() == item.getOrderStatus()) {
                vo.setVerificationBtn(1);
            } else if (OrderStatusEnum.WAIT_PAY.getStatus() == item.getOrderStatus()) {
                vo.setCancelBtn(1);
            } else if (OrderStatusEnum.RESERVE.getStatus() == item.getOrderStatus()) {
                vo.setCancelBtn(1);
            }
            vo.setAvatar(UrlUtil.toAbsoluteUrl(item.getAvatar()));
            vo.setGoodsImage(UrlUtil.toAbsoluteUrl(item.getGoodsImage()));
            vo.setCreateTime(TimeUtil.timestampToDate(item.getCreateTime()));
            vo.setUpdateTime(TimeUtil.timestampToDate(item.getUpdateTime()));
            vo.setWeekDay(TimeUtil.getWeekDay(item.getAppointTimeStart()));
            vo.setAppointTime(TimeUtil.timestampToDate(item.getAppointTimeStart(), "yyyy-MM-dd"));
            vo.setAppointTimeStartStr(TimeUtil.getHourMinute(item.getAppointTimeStart()));
            vo.setAppointTimeEndStr(TimeUtil.getHourMinute(item.getAppointTimeEnd()));
            vo.setOrderStatusName(orderStatusMap.get(vo.getOrderStatus()));
            vo.setIsDispatchName(dispatchMap.get(vo.getIsDispatch()));
            list.add(vo);
        }
        return PageResult.iPageHandle(resultDtoPage.getTotal(), resultDtoPage.getCurrent(), resultDtoPage.getSize(), list);
    }

    /**
     * @param params
     * @return
     */
    @Override
    public PageResult<OrderListVo> salesmanList(OrderPageParam params) {
        Page<OrderPageResultDto> page = new Page<>(params.getPageNo(), params.getPageSize());
        OrderDto pageDto = new OrderDto();
        BeanUtils.copyProperties(params, pageDto);
        Long startTime = StringUtils.isNotEmpty(params.getOrderTimeStart()) ? TimeUtil.dateToTimestamp(params.getOrderTimeStart()) : null;
        Long endTime = StringUtils.isNotEmpty(params.getOrderTimeEnd()) ? TimeUtil.dateToTimestamp(params.getOrderTimeEnd()) : null;
        endTime += 86400;
        pageDto.setOrderTimeStart(startTime);
        pageDto.setOrderTimeEnd(endTime);
        pageDto.setOrderType(params.getOrderType());
        page.setOptimizeCountSql(false);
        Page<OrderPageResultDto> resultDtoPage = orderMapper.salesmanPage(page, pageDto);
        if (resultDtoPage == null || CollectionUtils.isEmpty(resultDtoPage.getRecords())) {
            return PageResult.iPageHandle(page.getTotal(), page.getCurrent(), page.getSize(), Lists.newArrayList());
        }
        List<OrderListVo> list = new LinkedList<>();
        Map<Integer, String> orderStatusMap = OrderStatusEnum.getMap();
        Map<Integer, String> dispatchMap = OrderDispatchEnum.getMap();
        for (OrderPageResultDto item : resultDtoPage.getRecords()) {
            OrderListVo vo = new OrderListVo();
            BeanUtils.copyProperties(item, vo);
            if (OrderStatusEnum.CLOSE.getStatus() == item.getOrderStatus()) {
                vo.setDeleteBtn(1);
            } else if (OrderStatusEnum.SERVICING.getStatus() == item.getOrderStatus()) {
                vo.setVerificationBtn(1);
            } else if (OrderStatusEnum.WAIT_PAY.getStatus() == item.getOrderStatus()) {
                vo.setCancelBtn(1);
            } else if (OrderStatusEnum.RESERVE.getStatus() == item.getOrderStatus()) {
                vo.setCancelBtn(1);
            }
            vo.setAvatar(UrlUtil.toAbsoluteUrl(item.getAvatar()));
            vo.setGoodsImage(UrlUtil.toAbsoluteUrl(item.getGoodsImage()));
            vo.setCreateTime(TimeUtil.timestampToDate(item.getCreateTime()));
            vo.setUpdateTime(TimeUtil.timestampToDate(item.getUpdateTime()));
            vo.setWeekDay(TimeUtil.getWeekDay(item.getAppointTimeStart()));
            vo.setAppointTime(TimeUtil.timestampToDate(item.getAppointTimeStart(), "yyyy-MM-dd"));
            vo.setAppointTimeStartStr(TimeUtil.getHourMinute(item.getAppointTimeStart()));
            vo.setAppointTimeEndStr(TimeUtil.getHourMinute(item.getAppointTimeEnd()));
            vo.setOrderStatusName(orderStatusMap.get(vo.getOrderStatus()));
            vo.setIsDispatchName(dispatchMap.get(vo.getIsDispatch()));
            list.add(vo);
        }
        return PageResult.iPageHandle(resultDtoPage.getTotal(), resultDtoPage.getCurrent(), resultDtoPage.getSize(), list);
    }

    /**
     * 统计订单的金额数据
     *
     * @param params
     * @return
     */
    @Override
    public FinanceVo countList(OrderPageParam params) {
        OrderDto pageDto = new OrderDto();
        BeanUtils.copyProperties(params, pageDto);
        Long startTime = StringUtils.isNotEmpty(params.getOrderTimeStart()) ? TimeUtil.dateToTimestamp(params.getOrderTimeStart()) : null;
        Long endTime = StringUtils.isNotEmpty(params.getOrderTimeEnd()) ? TimeUtil.dateToTimestamp(params.getOrderTimeEnd()) : null;
        endTime += 86400;
        pageDto.setOrderTimeStart(startTime);
        pageDto.setOrderTimeEnd(endTime);
        List<OrderPageResultDto> orderPageResultDtos = orderMapper.countList(pageDto);
        BigDecimal totalAmount = BigDecimal.ZERO;
        int totalOrder = 0;
        for (OrderPageResultDto orderPageResultDto : orderPageResultDtos) {
            totalAmount = totalAmount.add(orderPageResultDto.getOrderAmount());
            totalOrder += orderPageResultDto.getTotalNum();
        }
        FinanceVo financeVo = new FinanceVo();
        financeVo.setTotalAmount(totalAmount);
        financeVo.setTotalOrder(totalOrder);
        BigDecimal totalRefundAmount = BigDecimal.ZERO;
        BigDecimal waitRefundAmount = BigDecimal.ZERO;
        if(orderPageResultDtos.size() != 0) {
            List<Long> longs = orderMapper.countGetId(pageDto);
            List<OrderRefundPageResultDto> orderRefundPageResultDtos = orderRefundMapper.selectListCount(longs);
            for (OrderRefundPageResultDto orderRefundPageResultDto : orderRefundPageResultDtos) {
                if (orderRefundPageResultDto.getRefundStatus() == OrderRefundStatusEnum.SUCCESS.getStatus()) {
                    totalRefundAmount = totalRefundAmount.add(orderRefundPageResultDto.getRefundAmount());
                } else if (OrderRefundStatusEnum.REFUNDING.getStatus() == orderRefundPageResultDto.getRefundStatus()
                        || OrderRefundStatusEnum.FAILURE.getStatus() == orderRefundPageResultDto.getRefundStatus()) {
                    waitRefundAmount = waitRefundAmount.add(orderRefundPageResultDto.getRefundAmount());
                }
            }
        }
        financeVo.setTotalRefundAmount(totalRefundAmount);
        financeVo.setWaitRefundAmount(waitRefundAmount);
        return financeVo;
    }

    /**
     * 订单详情
     *
     * @param id 主键参数
     * @return Order
     */
    @Override
    public OrderDetailVo detail(Long id) {
        Order model = orderMapper.selectOne(
                new QueryWrapper<Order>()
                        .eq("id", id)
                        .last("limit 1"));
        Assert.notNull(model, "数据不存在");
        OrderDetailVo vo = new OrderDetailVo();
        BeanUtils.copyProperties(model, vo);
        // 订单信息
        Map<Integer, String> orderStatusMap = OrderStatusEnum.getMap();
        Map<Integer, String> payMap = OrderPayStatusEnum.getMap();
        Map<Integer, String> payTypeMap = OrderPlayTypeEnum.getMap();
        Map<Integer, String> verificationMap = OrderVerificationStatusEnum.getMap();
        Map<Long, String> regionMap = regionService.getRegionMap();
        if (OrderStatusEnum.CLOSE.getStatus() == model.getOrderStatus()) {
            vo.setDeleteBtn(1);
        } else if (OrderStatusEnum.SERVICING.getStatus() == model.getOrderStatus()) {
            vo.setVerificationBtn(1);
            vo.setCancelBtn(1);
        } else if (OrderStatusEnum.WAIT_PAY.getStatus() == model.getOrderStatus()) {
            vo.setCancelBtn(1);
        } else if (OrderStatusEnum.RESERVE.getStatus() == model.getOrderStatus()) {
            vo.setCancelBtn(1);
        }
        vo.setOrderStatusName(orderStatusMap.get(model.getOrderStatus()));
        vo.setOrderTerminalName(ClientEnum.getMsgByCode(model.getOrderTerminal()));
        vo.setPayStatusName(payMap.get(model.getPayStatus()));
        vo.setPayWayName(payTypeMap.get(model.getPayWay()));
        vo.setVerificationStatusName(verificationMap.get(model.getVerificationStatus()));
        vo.setProvince(regionMap.get(model.getProvinceId()));
        vo.setCity(regionMap.get(model.getCityId()));
        vo.setDistrict(regionMap.get(model.getDistrictId()));
        vo.setAppointTimeStartStr(TimeUtil.getHourMinute(model.getAppointTimeStart()));
        vo.setAppointTimeEndStr(TimeUtil.getHourMinute(model.getAppointTimeEnd()));
        vo.setWeekDay(TimeUtil.getWeekDay(model.getAppointTimeStart()));
        vo.setAppointTime(TimeUtil.timestampToDate(model.getAppointTimeStart(), "yyyy-MM-dd"));
        vo.setCreateTime(TimeUtil.timestampToDate(model.getCreateTime()));
        vo.setPayTime(TimeUtil.timestampToDate(model.getPayTime()));
        vo.setFinishTime(TimeUtil.timestampToDate(model.getFinishTime()));
        vo.setCancelTime(TimeUtil.timestampToDate(model.getCancelTime()));
        // 用户昵称
        UserVo userVo = userService.detail(model.getUserId().intValue());
        vo.setNickname(userVo.getNickname());
        // 服务信息
        Long orderId = model.getId();
        OrderGoods orderGoods = orderGoodsService.getByOrderId(orderId);
        if (null != orderGoods) {
            vo.setGoodsId(orderGoods.getGoodsId());
            vo.setGoodsName(orderGoods.getGoodsName());
            vo.setUnitName(orderGoods.getUnitName());
            vo.setGoodsNum(orderGoods.getGoodsNum());
            vo.setGoodsPrice(orderGoods.getGoodsPrice());
            vo.setTotalPrice(orderGoods.getTotalPrice());
            vo.setTotalPayPrice(orderGoods.getTotalPayPrice());
            Long goodsId = orderGoods.getGoodsId();
            Goods goods = goodsService.getById(goodsId);
            if (null != goods) {
                vo.setGoodsImage(UrlUtil.toAbsoluteUrl(goods.getImage()));
            }
        }

        // 师傅信息
        if (vo.getStaffIds() != null) {
            List<String> list = Arrays.asList(vo.getStaffIds().split(","));
            ArrayList<Integer> integers = new ArrayList<>();
            list.forEach(l -> integers.add(Integer.valueOf(l)));
            List<StaffDetailVo> staff = new ArrayList<>();
            integers.forEach(integer -> {
                StaffDetailVo detail = staffService.detail(Long.valueOf(integer));
                if(Objects.nonNull(detail)){
                    staff.add(detail);
                }
            });
            vo.setStaff(staff);
        }

        // 日志信息
        List<OrderLogDetailVo> orderLogList = orderLogService.listByOrderId(orderId);
        vo.setOrderLogList(orderLogList);
        return vo;
    }

    /**
     * 订单新增
     *
     * @param orderParam 参数
     */
    @Override
    public void add(OrderParam orderParam) {
        Order model = new Order();
        model.setSn(orderParam.getSn());
        model.setUserId(orderParam.getUserId());
        model.setTransactionId(orderParam.getTransactionId());
        model.setStaffId(orderParam.getStaffId());
        model.setOrderType(orderParam.getOrderType());
        model.setOrderTerminal(orderParam.getOrderTerminal());
        model.setOrderStatus(orderParam.getOrderStatus());
        model.setPayStatus(orderParam.getPayStatus());
        model.setPayWay(orderParam.getPayWay());
        model.setGoodsPrice(orderParam.getGoodsPrice());
        model.setOrderAmount(orderParam.getOrderAmount());
        model.setTotalAmount(orderParam.getTotalAmount());
        model.setTotalNum(orderParam.getTotalNum());
        model.setUserRemark(orderParam.getUserRemark());
        model.setOrderRemarks(orderParam.getOrderRemarks());
        model.setVerificationCode(orderParam.getVerificationCode());
        model.setVerificationStatus(orderParam.getVerificationStatus());
        model.setContact(orderParam.getContact());
        model.setMobile(orderParam.getMobile());
        model.setProvinceId(orderParam.getProvinceId());
        model.setCityId(orderParam.getCityId());
        model.setDistrictId(orderParam.getDistrictId());
        model.setAddress(orderParam.getAddress());
        model.setIsDispatch(orderParam.getIsDispatch());
        model.setPayTime(orderParam.getPayTime());
        model.setCancelTime(orderParam.getCancelTime());
        model.setAppointTimeStart(orderParam.getAppointTimeStart());
        model.setAppointTimeEnd(orderParam.getAppointTimeEnd());
        model.setFinishTime(orderParam.getFinishTime());
        orderMapper.insert(model);
    }

    /**
     * 订单编辑
     *
     * @param orderParam 参数
     */
    @Override
    public void edit(OrderParam orderParam) {
        Order model = orderMapper.selectOne(
                new QueryWrapper<Order>()
                        .eq("id", orderParam.getId())
                        .last("limit 1"));

        Assert.notNull(model, "数据不存在!");

        model.setId(orderParam.getId());
        model.setSn(orderParam.getSn());
        model.setUserId(orderParam.getUserId());
        model.setTransactionId(orderParam.getTransactionId());
        model.setStaffId(orderParam.getStaffId());
        model.setOrderType(orderParam.getOrderType());
        model.setOrderTerminal(orderParam.getOrderTerminal());
        model.setOrderStatus(orderParam.getOrderStatus());
        model.setPayStatus(orderParam.getPayStatus());
        model.setPayWay(orderParam.getPayWay());
        model.setGoodsPrice(orderParam.getGoodsPrice());
        model.setOrderAmount(orderParam.getOrderAmount());
        model.setTotalAmount(orderParam.getTotalAmount());
        model.setTotalNum(orderParam.getTotalNum());
        model.setUserRemark(orderParam.getUserRemark());
        model.setOrderRemarks(orderParam.getOrderRemarks());
        model.setVerificationCode(orderParam.getVerificationCode());
        model.setVerificationStatus(orderParam.getVerificationStatus());
        model.setContact(orderParam.getContact());
        model.setMobile(orderParam.getMobile());
        model.setProvinceId(orderParam.getProvinceId());
        model.setCityId(orderParam.getCityId());
        model.setDistrictId(orderParam.getDistrictId());
        model.setAddress(orderParam.getAddress());
        model.setIsDispatch(orderParam.getIsDispatch());
        model.setPayTime(orderParam.getPayTime());
        model.setCancelTime(orderParam.getCancelTime());
        model.setAppointTimeStart(orderParam.getAppointTimeStart());
        model.setAppointTimeEnd(orderParam.getAppointTimeEnd());
        model.setFinishTime(orderParam.getFinishTime());
        orderMapper.updateById(model);
    }

    /**
     * 订单删除
     *
     * @param id 主键ID
     */
    @Override
    public void del(Long id) {
        Order model = orderMapper.selectOne(
                new QueryWrapper<Order>()
                        .eq("id", id)
                        .last("limit 1"));

        Assert.notNull(model, "数据不存在!");
        if (OrderStatusEnum.CLOSE.getStatus() != model.getOrderStatus()) {
            throw new OperateException("当前订单状态不允许删除!");
        }
        model.setIsDelete(GlobalConstant.DELETE);
        model.setDeleteTime(TimeUtil.timestamp());
        orderMapper.updateById(model);
    }

    @Override
    public StatisticsOrderVo statistics(Integer userId) {
        List<Order> list = null;
        if(userId != 0) {
            Map<String, Object> hash = new HashMap<>();
//            hash.put("user_id", userId);
            hash.put("status", 1);
            List<Salesman> salesmen = salesmanMapper.selectByMap(hash);
            if(salesmen == null || salesmen.size() == 0) {
                throw new OperateException("你不是推销员！！！");
            }
            list = orderMapper.selectList(new QueryWrapper<Order>().eq("salesman_user_id", userId).eq("is_delete", 0));
        } else {
            list = super.list();
        }
        if (CollectionUtils.isEmpty(list)) {
            return new StatisticsOrderVo();
        }
        list = list.stream().filter(item -> item.getIsDelete() == 0).collect(Collectors.toList());
        long waitPayCount = list.stream().map(Order::getOrderStatus).filter(item -> OrderStatusEnum.WAIT_PAY.getStatus() == item).count();
        long reserveCount = list.stream().map(Order::getOrderStatus).filter(item -> OrderStatusEnum.RESERVE.getStatus() == item).count();
        long servicingCount = list.stream().map(Order::getOrderStatus).filter(item -> OrderStatusEnum.SERVICING.getStatus() == item).count();
        long finishedCount = list.stream().map(Order::getOrderStatus).filter(item -> OrderStatusEnum.FINISHED.getStatus() == item).count();
        long closeCount = list.stream().map(Order::getOrderStatus).filter(item -> OrderStatusEnum.CLOSE.getStatus() == item).count();
        StatisticsOrderVo orderVo = new StatisticsOrderVo();
        orderVo.setTotalCount(list.size());
        orderVo.setWaitPayCount((int) waitPayCount);
        orderVo.setReserveCount((int) reserveCount);
        orderVo.setServicingCount((int) servicingCount);
        orderVo.setFinishedCount((int) finishedCount);
        orderVo.setCloseCount((int) closeCount);
        return orderVo;
    }

    @Override
    public void remark(Long id, Integer userId, String remark) {
        Order model = orderMapper.selectOne(
                new QueryWrapper<Order>()
                        .eq("id", id)
                        .last("limit 1"));

        Assert.notNull(model, "数据不存在!");
        model.setOrderRemarks(remark);
        model.setUpdateTime(TimeUtil.timestamp());
        orderMapper.updateById(model);
        //保存日志
        this.saveOrderLog(id, userId.longValue(), OrderLogEnum.SHOP_REMARK_ORDER.getDesc());
    }

    @Override
    public void cancelOrder(Long id, Integer userId) throws WxPayException, AlipayApiException {
        Order model = orderMapper.selectOne(
                new QueryWrapper<Order>()
                        .eq("id", id)
                        .last("limit 1"));

        Assert.notNull(model, "数据不存在!");
        // 待支付 直接取消
        if (OrderStatusEnum.WAIT_PAY.getStatus() == model.getOrderStatus()) {
            model.setOrderStatus(OrderStatusEnum.CLOSE.getStatus());
            model.setUpdateTime(TimeUtil.timestamp());
            model.setCancelTime(TimeUtil.timestamp());
            orderMapper.updateById(model);
            this.saveOrderLog(id, userId.longValue(), OrderLogEnum.SHOP_CANCEL_ORDER.getDesc());
            //如果是微信支付 直接关闭订单
            if (PaymentEnum.WX_PAY.getCode() == model.getPayWay()){
                WxPayServiceUtils.wxPayService(model.getPayChannel()).closeOrderV3(model.getSn());
            }

            //如果是支付宝支付，则关闭订单

            return;
        }
        // 预约中 如果指派师傅 则不允许取消
        if (OrderStatusEnum.RESERVE.getStatus() == model.getOrderStatus() || OrderStatusEnum.SERVICING.getStatus() == model.getOrderStatus()) {
            model.setOrderStatus(OrderStatusEnum.CLOSE.getStatus());
            model.setUpdateTime(TimeUtil.timestamp());
            model.setCancelTime(TimeUtil.timestamp());
            orderMapper.updateById(model);
            refundService.createAndRefund(model.getId(), RefundOperateEnum.TYPE_ADMIN.getType());
            this.saveOrderLog(id, userId.longValue(), OrderLogEnum.SHOP_CANCEL_ORDER.getDesc());

            // 发送通知 (订单被系统取消关闭)
            try {
                Map<String, String> config = new LinkedHashMap<>();
                config.put("scene", String.valueOf(NoticeEnum.U_ORDER_CANCEL.getCode()));
                config.put("mobile", model.getMobile().trim());

                Map<String, String> params = new LinkedHashMap<>();
                params.put("user_name", model.getContact());
                params.put("order_sn", model.getSn());
                (new NoticeDriver()).handle(config, params);
            } catch (Exception e) {
                System.out.println(e.getMessage());
            }

            // 发送通知 (平台取消派单通知: 师傅)
            try {
                if (model.getIsDispatch() == 1) {
                    StaffDetailVo staffVo = staffService.detail(model.getStaffId());

                    Map<String, String> config = new LinkedHashMap<>();
                    config.put("scene", String.valueOf(NoticeEnum.F_CANCEL_DISPATCH_ORDER.getCode()));
                    config.put("mobile", staffVo.getMobile().trim());

                    Map<String, String> params = new LinkedHashMap<>();
                    params.put("staff_name", staffVo.getName());
                    (new NoticeDriver()).handle(config, params);
                }
            } catch (Exception e) {
                System.out.println(e.getMessage());
            }

            // 发送通知 (退款成功, 余额支付在这发, 微信支付宝支付走退款回调发)
            if (model.getPayWay().equals(PaymentEnum.WALLET_PAY.getCode())) {
                try {
                    Map<String, String> config = new LinkedHashMap<>();
                    config.put("scene", NoticeEnum.U_ORDER_REFUND.getCode() + "");
                    config.put("mobile", model.getMobile());

                    Map<String, String> params = new LinkedHashMap<>();
                    params.put("user_name", model.getContact());
                    params.put("order_sn", model.getSn());
                    (new NoticeDriver()).handle(config, params);
                } catch (Exception e) {
                    System.out.println(e.getMessage());
                }
            }
        }
    }

    @Override
    public void cancelOvertimeOrder(String orderNo, int userId) throws Exception {
        Order order = orderMapper.selectOne(
                new QueryWrapper<Order>()
                        .eq("sn", orderNo)
                        .last("limit 1"));

        Assert.notNull(order, "数据不存在!");
        order.setOrderStatus(OrderStatusEnum.CLOSE.getStatus());
        order.setCancelTime(TimeUtil.timestamp());
        order.setOrderRemarks("订单预约超时关闭");
        orderMapper.updateById(order);
        refundService.createAndRefund(order.getId(), RefundOperateEnum.TYPE_SYSTEM.getType());
        this.saveOrderLog(order.getId(), (long) userId, OrderLogEnum.SYSTEM_CANCEL_APPOINT_ORDER.getDesc());
    }

    @Override
    public Order getBySn(String outTradeNo) {
        LambdaQueryWrapper<Order> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Order::getSn, outTradeNo);
        lambdaQueryWrapper.last("limit 1");
        return super.getOne(lambdaQueryWrapper);
    }

    @Override
    public void dispatchStaff(Long id, Integer[] staffIds, Integer userId) {
        Order model = orderMapper.selectOne(
                new QueryWrapper<Order>()
                        .eq("id", id)
                        .last("limit 1"));
        Assert.notNull(model, "数据不存在!");
        // 是否已派单状态
        Integer isDispatch = model.getIsDispatch();
        Long oldStaffId = model.getStaffId();

//        if (OrderStatusEnum.SERVICING.getStatus() == model.getOrderStatus()
//                && OrderDispatchEnum.IS_DISPATCH.getStatus() == model.getIsDispatch()) {
//            throw new OperateException("订单已经有师傅进行服务，不能进行派单了");
//        }
        // 获取所有的预约上门时间的订单
        Long appointTimeStart = model.getAppointTimeStart();
        LambdaQueryWrapper<Order> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Order::getAppointTimeStart, appointTimeStart);
        lambdaQueryWrapper.eq(Order::getOrderStatus, OrderStatusEnum.SERVICING.getStatus());
        lambdaQueryWrapper.eq(Order::getIsDelete, GlobalConstant.DELETE);
        List<Order> orders = baseMapper.selectList(lambdaQueryWrapper);
        String[] array = Arrays.stream(staffIds)
                .map(Object::toString)
                .toArray(String[]::new);

        for (Order order : orders) {
            String[] split = order.getStaffIds().split(",");
            if (ArrayUtil.containsAny(split, array)) {
                throw new OperateException("指派的师傅中在预约的时间是有单的");
            }
        }
        model.setStaffIds(String.join(",", array));
        model.setIsDispatch(OrderDispatchEnum.IS_DISPATCH.getStatus());
	    model.setUpdateTime(TimeUtil.timestamp());
	    model.setOrderStatus(OrderStatusEnum.SERVICING.getStatus());
	    model.setVerificationStatus(OrderVerificationStatusEnum.WAIT_VERIFICATION.getStatus());
	    model.setVerificationCode(SnUtils.get6RandomCode());
	    model.setUpdateTime(TimeUtil.timestamp());
	    orderMapper.updateById(model);
	    this.saveOrderLog(id, userId.longValue(), OrderLogEnum.SHOP_DISPATCH_STAFF.getDesc());

        Object dispatchLimit = RedisUtil.get("dispatch:limit:" + model.getId());
        if (isDispatch == 0 && dispatchLimit == null) {
            RedisUtil.set("dispatch:limit:" + model.getId(), 1, 60);
            List<Staff> finishStaff = staffService.listByIds(Arrays.asList(staffIds));
            Map<Long, Long> orderGoodsMap = orderGoodsService.listByOrderIds(Collections.singletonList(model.getId())).stream().collect(Collectors.toMap(item -> item.getOrderId(), item -> item.getGoodsId(), (a, b) -> b));
            Goods goods = goodsService.getById(orderGoodsMap.get(model.getId()));
            for (Staff staff1 : finishStaff) {

                // 发送通知 (订单确认服务通知: 师傅)
                try {
                    Map<String, String> config = new LinkedHashMap<>();
                    config.put("scene", String.valueOf(NoticeEnum.F_ORDER_STAY_CONFIRM.getCode()));
                    config.put("mobile", staff1.getMobile());
                    Map<String, String> params = new LinkedHashMap<>();
                    params.put("staff_name", staff1.getName());
                    params.put("goods_name", goods.getName());
                    params.put("order_number", "分配一下");
                    (new NoticeDriver()).handle(config, params);
                } catch (Exception ignored) {
                }
            }

        }
    }

    @Override
    public Boolean qualityOrder(Long id, Long staffId, Integer userId) {
        Order model = orderMapper.selectOne(
                new QueryWrapper<Order>()
                        .eq("id", id)
                        .last("limit 1"));
        Assert.notNull(model, "数据不存在!");
        // 判断订单是否是服务中状态
        if (OrderStatusEnum.SERVICING.getStatus() == model.getOrderStatus()
                && OrderDispatchEnum.IS_DISPATCH.getStatus() == model.getIsDispatch()) {
            throw new OperateException("订单已经有师傅进行服务，不能进行派单了");
        }
        // 获取师傅在一天里面的所有订单
        LambdaQueryWrapper<Order> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.ge(Order::getAppointTimeStart, convertTime(model.getAppointTimeStart(), true));
        lambdaQueryWrapper.le(Order::getAppointTimeEnd, convertTime(model.getAppointTimeEnd(), false));
        List<Integer> orderStatusList = Lists.newArrayList(OrderStatusEnum.SERVICING.getStatus(), OrderStatusEnum.RESERVE.getStatus());
        lambdaQueryWrapper.in(Order::getOrderStatus, orderStatusList);
//        lambdaQueryWrapper.eq(Order::getStaffId, staffId);
        // 查找订单有没有师傅进行服务
        lambdaQueryWrapper.apply("FIND_IN_SET(" + staffId + ", `staff_ids`)");
        List<Order> staffOrders = this.baseMapper.selectList(lambdaQueryWrapper);
        Order bakOrder = null;
        for (Order staffOrder : staffOrders) {
            if(staffOrder.getAppointTimeStart() == model.getAppointTimeStart() && staffOrder.getAppointTimeEnd() == model.getAppointTimeEnd()) {
                throw new OperateException("该师傅在此预约时间段中已有单,请更换师傅");
            }
            // 如果师傅订单预约结束时间等于订单的开始时间
            else if(staffOrder.getAppointTimeEnd() == model.getAppointTimeStart()) {
                bakOrder = staffOrder;
            }
        }
        // 如果bakOrder不等于null，代表当前单的上一单是在一起的，判断是不是5公里内，如果不是则不可以接这个单
        if(bakOrder != null) {
            double[] modelLongitudeAndLatitude = getLongitudeAndLatitude(model);
            double[] bakLongitudeAndLatitude = getLongitudeAndLatitude(bakOrder);
            Double distanceByGaoDe = RangeCalculationUtil.getDistanceByGaoDe(modelLongitudeAndLatitude[0], modelLongitudeAndLatitude[1], bakLongitudeAndLatitude[0], bakLongitudeAndLatitude[1]);
            log.info("当前订单和上一单的距离为：{}", distanceByGaoDe);
            if(distanceByGaoDe > 5000) {
                throw new OperateException("该师傅应该不能接这个单，这单跟上一单的距离太远，请更换师傅");
            }
        }
        return true;
    }

    private double[] getLongitudeAndLatitude(Order model) {
        String pcda = "province_id:" + model.getProvinceId() +
                "city_id:" + model.getCityId() +
                "district_id" + model.getDistrictId() +
                "address" + model.getAddress();
        double longitude = 0;
        double latitude = 0;
        if (redisTemplate.hasKey(pcda)) {
            String result = redisTemplate.opsForValue().get(pcda);
            String[] split = result.split(",");
            longitude = Double.parseDouble(split[0]);
            latitude = Double.parseDouble(split[1]);
        } else {
            HashMap<String, Object> userAddressHash = new HashMap<>();
            userAddressHash.put("province_id", model.getProvinceId());
            userAddressHash.put("city_id", model.getCityId());
            userAddressHash.put("district_id", model.getDistrictId());
            userAddressHash.put("address", model.getAddress());
            userAddressHash.put("is_delete", 0);
            List<UserAddress> userAddresses = userAddressMapper.selectByMap(userAddressHash);
            for (UserAddress userAddress : userAddresses) {
                if (StringUtil.isNotEmpty(userAddress.getLongitude()) && StringUtil.isNotEmpty(userAddress.getLatitude())) {
                    String pcda1 = "province_id:" + userAddress.getProvinceId() +
                            "city_id:" + userAddress.getCityId() +
                            "district_id" + userAddress.getDistrictId() +
                            "address" + userAddress.getAddress();
                    longitude = Double.parseDouble(userAddress.getLongitude());
                    latitude = Double.parseDouble(userAddress.getLatitude());
                    redisTemplate.opsForValue().set(pcda1, longitude + "," + latitude);
                    break;
                }
            }
        }
        return new double[]{longitude, latitude};
    }

    private Long convertTime(Long timestamp, Boolean startOrEnd) {
        Instant instant = Instant.ofEpochSecond(timestamp);
        LocalDateTime dateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
        if(startOrEnd) {
            LocalDateTime localDateTime = dateTime.withHour(0).withSecond(0).withMinute(0);
            return localDateTime.toEpochSecond(java.time.OffsetDateTime.now().getOffset());
        }
        LocalDateTime localDateTime = dateTime.withHour(23).withSecond(59).withMinute(59);
        return localDateTime.toEpochSecond(java.time.OffsetDateTime.now().getOffset());
    }

    @Override
    public void verificationOrder(Long id, String code, Integer userId) {
        Order model = orderMapper.selectOne(
                new QueryWrapper<Order>()
                        .eq("id", id)
                        .last("limit 1"));
        Assert.notNull(model, "数据不存在!");
        if (OrderStatusEnum.SERVICING.getStatus() != model.getOrderStatus()) {
            throw new OperateException("只有服务中的订单才能进行核销");
        }
        String verificationCode = model.getVerificationCode();
        if (!verificationCode.equalsIgnoreCase(code)) {
            throw new OperateException("核销码错误,请重新输入");
        }
        model.setVerificationStatus(OrderVerificationStatusEnum.VERIFICATION.getStatus());
        model.setOrderStatus(OrderStatusEnum.FINISHED.getStatus());
        model.setFinishTime(TimeUtil.timestamp());
        model.setUpdateTime(TimeUtil.timestamp());
        orderMapper.updateById(model);
        this.saveOrderLog(id, userId.longValue(), OrderLogEnum.SHOP_VERIFICATION.getDesc());

        // 发送通知 (师傅核销)
        try {
            Map<String, String> config = new LinkedHashMap<>();
            config.put("scene", String.valueOf(NoticeEnum.U_ORDER_COMPLETE.getCode()));
            config.put("mobile", model.getMobile().trim());

            Map<String, String> params = new LinkedHashMap<>();
            params.put("user_name", model.getContact());
            params.put("order_sn", model.getSn().trim());
            (new NoticeDriver()).handle(config, params);
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }

    private void saveOrderLog(Long orderId, Long userId, String context) {
        OrderLog orderLog = new OrderLog();
        orderLog.setType(OperateEnum.TYPE_ADMIN.getType());
        //orderLog.setChannel(0);
        orderLog.setOrderId(orderId);
        orderLog.setOperatorId(userId);
        orderLog.setContent(context);
        orderLog.setCreateTime(TimeUtil.timestamp());
        orderLog.setUpdateTime(TimeUtil.timestamp());
        orderLogService.saveEntity(orderLog);
    }

    @Override
    public Boolean existOrderByStaffId(Long staffId) {
        LambdaQueryWrapper<Order> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Order::getStaffId, staffId);
        lambdaQueryWrapper.ge(Order::getOrderStatus, OrderStatusEnum.SERVICING.getStatus());
        lambdaQueryWrapper.last("limit 1");
        Order model = super.getOne(lambdaQueryWrapper);
        return model == null ? Boolean.FALSE : Boolean.TRUE;
    }

    @Override
    public boolean updateOrderStatusToPaid(String outTradeNo, String transactionId) throws Exception {
        //处理重复的通知
        //接口调用的幂等性：无论接口被调用多少次，产生的结果是一致的。
        LambdaQueryWrapper<Order> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Order::getSn, outTradeNo);
        lambdaQueryWrapper.last("limit 1");
        Order order = super.getOne(lambdaQueryWrapper);
        Assert.notNull(order, "订单未关联到对应的订单");
        Integer payStatus = order.getPayStatus();
        if (OrderPayStatusEnum.WAIT_PAY.getStatus() != payStatus) {
            return true;
        }
        WxPayOrderQueryV3Result wxPayOrderQueryV3Result = WxPayServiceUtils.wxPayService(order.getPayChannel()).queryOrderV3(transactionId, outTradeNo);
        String tradeState = wxPayOrderQueryV3Result.getTradeState();
        transactionId = wxPayOrderQueryV3Result.getTransactionId();
        if ("SUCCESS".equals(tradeState)) {
            order.setTransactionId(transactionId);
            //更新订单状态
            order.setOrderStatus(OrderStatusEnum.RESERVE.getStatus());
            order.setPayStatus(OrderPayStatusEnum.PAY.getStatus());
            order.setPayTime(TimeUtil.timestamp());
            order.setPayWay(OrderPlayTypeEnum.WECHAT_PAY.getType());
            order.setUpdateTime(TimeUtil.timestamp());
            orderMapper.updateById(order);
            //记录支付日志
            this.saveOrderLog(order.getId(), order.getUserId(), OrderLogEnum.USER_PAY_ORDER.getDesc());
            return true;
        }

        return false;
    }

    @Override
    public List<Order> getNoStaffByDuration(int minutes) {
        LocalDateTime localDateTime = LocalDateTime.now();
        LocalDateTime time = localDateTime.minusMinutes(minutes);
        long createTime = time.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli() / 1000;
        LambdaQueryWrapper<Order> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.isNull(Order::getStaffId);
        lambdaQueryWrapper.eq(Order::getOrderStatus, OrderStatusEnum.RESERVE.getStatus());
        lambdaQueryWrapper.eq(Order::getOrderType, GlobalConstant.DELETE);
        lambdaQueryWrapper.le(Order::getCreateTime, createTime);
        List<Order> orderInfoList = super.list(lambdaQueryWrapper);
        return orderInfoList;
    }

    @Override
    public void verificationByDuration(Integer hour) {
        LocalDateTime localDateTime = LocalDateTime.now();
        LocalDateTime time = localDateTime.minusHours(hour);
        long createTime = time.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli() / 1000;
        LambdaQueryWrapper<Order> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Order::getOrderStatus, OrderStatusEnum.SERVICING.getStatus());
        lambdaQueryWrapper.eq(Order::getVerificationStatus, OrderVerificationStatusEnum.WAIT_VERIFICATION.getStatus());
        lambdaQueryWrapper.le(Order::getCreateTime, createTime);
        List<Order> orderInfoList = super.list(lambdaQueryWrapper);
        if (CollectionUtils.isEmpty(orderInfoList)) {
            return;
        }
        for (Order order : orderInfoList) {
            order.setOrderStatus(OrderStatusEnum.FINISHED.getStatus());
            order.setFinishTime(TimeUtil.timestamp());
            order.setVerificationStatus(OrderVerificationStatusEnum.VERIFICATION.getStatus());
            order.setUpdateTime(TimeUtil.timestamp());

            // 发送通知 (师傅核销)
            try {
                Map<String, String> config = new LinkedHashMap<>();
                config.put("scene", String.valueOf(NoticeEnum.U_ORDER_COMPLETE.getCode()));
                config.put("mobile", order.getMobile());

                Map<String, String> params = new LinkedHashMap<>();
                params.put("user_name", order.getContact());
                params.put("order_sn", order.getSn());
                (new NoticeDriver()).handle(config, params);
            } catch (Exception e) {
                System.out.println(e.getMessage());
            }
        }
        super.updateBatchById(orderInfoList);
    }

    @Override
    public List<Order> getOvertimeOrder() {
        long currentTime = System.currentTimeMillis() / 1000;
        LambdaQueryWrapper<Order> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.isNull(Order::getStaffId);
        lambdaQueryWrapper.eq(Order::getOrderStatus, OrderStatusEnum.RESERVE.getStatus());
        lambdaQueryWrapper.le(Order::getAppointTimeEnd, currentTime);
        List<Order> orderInfoList = super.list(lambdaQueryWrapper);
        return orderInfoList;
    }

    @Override
    public void updateEntityById(Order orderInfo) {
        super.updateById(orderInfo);
    }

    @Override
    public List<Order> getNoPayOrderByDuration(Integer minutes) {
        LocalDateTime localDateTime = LocalDateTime.now();
        LocalDateTime time = localDateTime.minusMinutes(minutes);
        long createTime = time.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli() / 1000;
        LambdaQueryWrapper<Order> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Order::getPayStatus, OrderPayStatusEnum.WAIT_PAY.getStatus());
        lambdaQueryWrapper.eq(Order::getOrderStatus, OrderStatusEnum.WAIT_PAY.getStatus());
        lambdaQueryWrapper.le(Order::getCreateTime, createTime);
        List<Order> orderInfoList = super.list(lambdaQueryWrapper);
        return orderInfoList;
    }

    @Override
    public void checkOrderStatus(Long orderId) throws Exception {
        log.info("根据订单号核实订单状态 ===> {}", orderId);
        //调用微信支付查单接口
        Order model = orderMapper.selectOne(
                new QueryWrapper<Order>()
                        .eq("id", orderId)
                        .last("limit 1"));
        if (OrderPayStatusEnum.PAY.getStatus() == model.getPayStatus()) {
            return;
        }
        WxPayOrderQueryV3Result queryOrderV3 = WxPayServiceUtils.wxPayService(model.getPayChannel()).queryOrderV3(model.getTransactionId(), model.getSn());
        String tradeState = queryOrderV3.getTradeState();
        //判断订单状态
        if ("SUCCESS".equals(tradeState)) {
            // 修改订单的支付信息
            model.setPayTime(TimeUtil.dateToTimestamp(TimeUtil.getStringByRFC3339(queryOrderV3.getSuccessTime())));
            model.setOrderStatus(OrderStatusEnum.RESERVE.getStatus());
            model.setPayStatus(OrderPayStatusEnum.PAY.getStatus());
            model.setPayWay(OrderPlayTypeEnum.WECHAT_PAY.getType());
            model.setTransactionId(queryOrderV3.getTransactionId());
            model.setUpdateTime(TimeUtil.timestamp());
            orderMapper.updateById(model);
            // 记录日志
            this.saveOrderLog(orderId, model.getUserId(), OrderLogEnum.USER_PAY_ORDER.getDesc());
        } else if ("CLOSE".equals(tradeState)) {
            log.warn("核实订单已关闭 ===> {}", model.getSn());
            return;
        } else {
            log.warn("核实订单未支付 ===> {}", model.getSn());
            //如果订单未支付，则调用关单接口
            //this.cancelPay(model.getId());
            WxPayServiceUtils.wxPayService(model.getPayChannel()).closeOrderV3(model.getSn());
            //更新本地订单状态
            model.setOrderStatus(OrderStatusEnum.CLOSE.getStatus());
            model.setCancelTime(TimeUtil.timestamp());
            orderMapper.updateById(model);
            this.saveOrderLog(orderId, model.getUserId(), OrderLogEnum.SYSTEM_CANCEL_ORDER.getDesc());
        }
    }

    @Override
    public void bindAnnualService(Map<String, String> params) {
        Order order = new Order();
        order.setId(Long.valueOf(params.get("orderId")));
        String staffId = params.get("staffId");
        order.setStaffId(Long.valueOf(staffId));
        order.setStaffIds(staffId.toString());
        orderMapper.updateById(order);
        OrderGoods byOrderId = orderGoodsService.getByOrderId(order.getId());
        Goods goods = goodsService.getById(byOrderId.getGoodsId());
        List<AnnualService> annualServices = iAnnualServiceService.getBaseMapper().selectList(new LambdaQueryWrapper<AnnualService>()
                .eq(AnnualService::getIsDelete, GlobalConstant.NOT_DELETE)
                .eq(AnnualService::getOrderId, order.getId())
                .gt(AnnualService::getDate, TimeUtil.timestamp()));
        if(CollectionUtils.isEmpty(annualServices)) {
            return;
        }
        annualServices.forEach(item -> {
            item.setStaffId(Integer.valueOf(staffId));
            item.setUpdateTime(TimeUtil.timestamp());
        });
        Staff staff = staffService.getById(Long.valueOf(staffId));
        if (!iAnnualServiceService.updateBatchById(annualServices)) {
            throw new OperateException("批量修改保姆服务失败");
        }
        // 给师傅发送信息
        try {
            Map<String, String> config = new LinkedHashMap<>();
            config.put("scene", String.valueOf(NoticeEnum.F_ORDER_STAY_CONFIRM.getCode()));
            config.put("mobile", staff.getMobile());
            Map<String, String> params1 = new LinkedHashMap<>();
            params1.put("staff_name", staff.getName());
            params1.put("goods_name", goods.getName());
            params1.put("order_number", String.valueOf(annualServices.size()));
            (new NoticeDriver()).handle(config, params1);
        } catch (Exception ignored) {
            log.error("师傅发送消息失败");
        }
    }
}
